import { compare_A_B } from '..';
import { emptyData } from '../../../../../Classes/emptyData';
import { empty_clone } from '../../../../empty_clone';
import { ObjectOnlyPushSet } from '../../../../ObjectOnlyPushSet_operate';
import {
  diff_prop,
  diff_prop_typeArr,
  quick_increase_or_delete,
  quick_increase_or_delete_instance,
} from '../../../Classes/cla_diff_prop';
import {
  explore_for_diff,
  prop_static_child_type_arr,
} from '../../../Classes/cla_explore_for_diff';
import { key_ind_arr } from '../../../Types';
import {
  compare_linkObj,
  compare_linkObj_data_or_delete_part,
} from '../Classes/cla_compare_linkObj';
import {
  compare_more_same,
  prop_static_more_same_index,
} from '../Classes/cla_compare_more_same';
import { same_describe } from '../Classes/cla_deepth_diff_type';
import { seek_for_more_same } from './seek_for_more_same';

/**
 * 数组 严格比对 开关
 */
let strict_more_same = false;

/**
 * 使用 严格 顺序 比对
 * @param use_strict true 使用 false 不使用
 */
export function set_strict_more_same(use_strict: boolean) {
  strict_more_same = use_strict;
}

/**
 * 深度 对比
 * @param {explore_for_diff} tA
 * @param {explore_for_diff} tB
 */
export function compare_by_type(tA: explore_for_diff, tB: explore_for_diff) {
  let ret = new compare_linkObj(tB._$223_current_type);

  // 在 数组 情况下 且 严格 顺序 比对 为 false 时
  let arr_for_seek_more_same = () => {
    let arr_more_same_compare_obj = compare_by_arr(tA, tB);
    Object.assign(ret, arr_more_same_compare_obj);
  };

  if (tB._$223_current_type == 'array' && !strict_more_same) {
    arr_for_seek_more_same();
    return ret;
  }

  /**
   * 逻辑 修订
   * 当前 循环 只为 新增项
   * 两者 共有项 后续 比对
   */
  // 遍历 tB 类 类别 集
  for_type: for (const key_type of <key_ind_arr>(
    tB[prop_static_child_type_arr]
  )) {
    // 当 主体元素 tA 不包含 当前 类 类别 时
    if (!(<key_ind_arr>tA[prop_static_child_type_arr]).includes(key_type)) {
      // 将 比对元素 tB 类 类别 集合 全 设置 为 新增
      packret_LinkObj(
        ret,
        increase_part_arr(tB, <key_ind_arr>tB[key_type]),
        'increase_part'
      );
      continue for_type;
    }

    // 遍历 tB 类 类别 中的 元素
    for_type_key_index: for (const tb_key_type_index of <key_ind_arr>(
      tB[key_type]
    )) {
      // 将 tA 类别 下 不存在 的 tb_key_type_index 标记为 新增项
      if (!(<key_ind_arr>tA[key_type]).includes(tb_key_type_index)) {
        packret_LinkObj(
          ret,
          increase_part_arr(tB, tb_key_type_index),
          'increase_part'
        );
        continue for_type_key_index;
      }

      ObjectOnlyPushSet(
        ret,
        tb_key_type_index,
        compare_A_B(
          <explore_for_diff>tA[tb_key_type_index],
          <explore_for_diff>tB[tb_key_type_index]
        )
      );
    }
  }

  /**
   * 逻辑 修订
   * 检测 删除项
   */
  // 遍历 tA 类 类别 集
  for_type: for (const key_type of <key_ind_arr>(
    tA[prop_static_child_type_arr]
  )) {
    // 当 tB 没有 这个 类 类别
    if (!(<key_ind_arr>tB[prop_static_child_type_arr]).includes(key_type)) {
      // 将 tA 该类类别 所有内容 标记为 删除项
      packret_LinkObj(
        ret,
        delete_part_arr(tA, <key_ind_arr>tA[key_type]),
        'delete_part'
      );
      continue for_type;
    }

    // 遍历 tA 类 类别 中的 元素
    for_type_key_index_tA: for (const ta_key_type_index of <key_ind_arr>(
      tA[key_type]
    )) {
      if (!(<key_ind_arr>tB[key_type]).includes(ta_key_type_index)) {
        // 将 tA 该类类别 所有内容 标记为 删除项
        packret_LinkObj(
          ret,
          delete_part_arr(tA, ta_key_type_index),
          'delete_part'
        );
        continue for_type_key_index_tA;
      }
    }
  }

  return ret;
}

/**
 * 深度 对比
 * @param {explore_for_diff} tA
 * @param {explore_for_diff} tB
 */
export function compare_by_arr(tA: explore_for_diff, tB: explore_for_diff) {
  let linked_arr = new compare_linkObj(tB._$223_current_type);

  /**
   * 元素 比对 结果 完全 没有 相同的
   */
  let val_no_same_ind_arr: key_ind_arr = [];

  /**
   * 逻辑 修订
   * 当前 循环 只为 新增项
   * 两者 共有项 后续 比对
   */
  ta_for_type: for (const key_type of <key_ind_arr>(
    tA[prop_static_child_type_arr]
  )) {
    // 当 tB 不包含 当前 类 类别 时
    if (!(<key_ind_arr>tB[prop_static_child_type_arr]).includes(key_type)) {
      // 将 所有 tB 标识为 新增项
      packret_LinkObj(
        linked_arr,
        increase_part_arr(tB, <key_ind_arr>tB[key_type]),
        'increase_part'
      );
      continue ta_for_type;
    }

    let clone_cur_ta_type_arr = empty_clone(<key_ind_arr>tA[key_type]);

    let clone_cur_tb_type_arr = empty_clone(<key_ind_arr>tB[key_type]);

    // 以 当前 tA 类别 项 为主 进行 循环
    ta_for_type_ind: for (
      let ta_ind = 0;
      ta_ind < clone_cur_ta_type_arr.length;
      ta_ind++
    ) {
      /**
       *  tA 的 类型 index 值
       */
      const ta_key_type_ind = clone_cur_ta_type_arr[ta_ind];

      /**
       * 当前 节点 所有 对比值
       */
      let for_all_compare = new compare_more_same();

      /**
       * 当前 暴露 的 tA 属性 项
       */
      let ta_cur_type_for_diff = <explore_for_diff>tA[ta_key_type_ind];

      let settle_func = (
        more_same_index: string | number,
        ta_key_type_ind: string | number
      ) => {
        // 移除 clone_cur_tb_type 中 的 当前 最高分项
        clone_cur_tb_type_arr.splice(
          clone_cur_tb_type_arr.indexOf(more_same_index),
          1
        );

        ta_ind--;

        // 移除 clone_cur_ta_type 中 的 对应 ta_key_type_ind
        clone_cur_ta_type_arr.splice(
          clone_cur_ta_type_arr.indexOf(ta_key_type_ind),
          1
        );

        (<diff_prop>for_all_compare[more_same_index]).same_ind =
          ta_key_type_ind;

        // 将 当前 项 添加到 主 返回项 中
        ObjectOnlyPushSet(
          linked_arr,
          more_same_index,
          for_all_compare[more_same_index]
        );

        for_all_compare[prop_static_more_same_index] = more_same_index;
      };
      if (clone_cur_tb_type_arr.length == 0) {
        break ta_for_type_ind;
      }
      // 以 tB 类别 项 为辅 进行 次循环比对
      tb_for_type_ind: for (
        let tb_ind = 0;
        tb_ind < clone_cur_tb_type_arr.length;
        tb_ind++
      ) {
        const tb_key_type_ind = clone_cur_tb_type_arr[tb_ind];

        /**
         * 当前 暴露 的 tB 属性 项
         */
        let tb_cur_type_for_diff = <explore_for_diff>tB[tb_key_type_ind];

        let compared_ret = compare_A_B(
          ta_cur_type_for_diff,
          tb_cur_type_for_diff
        );

        // 将 tA 属性项 与 tB 属性项 进行 比对
        ObjectOnlyPushSet(for_all_compare, tb_key_type_ind, compared_ret);
      }

      /**
       * 获取 比对象 描述 集 对应 的 最相似的 tb_key_type_index
       */
      let { value_same_describe, more_same_index } =
        seek_for_more_same(for_all_compare);

      // 当元素 比对 结果 是 不相同 时 进行下次 tA type_ind 循环
      if (
        value_same_describe == same_describe.noSame ||
        value_same_describe == same_describe.valNoSame
      ) {
        continue ta_for_type_ind;
      }

      // 此处 为 相似 项
      settle_func(
        (<key_ind_arr>tB[key_type]).indexOf(more_same_index).toString(),
        ta_key_type_ind
      );
    }

    // 将 剩余 tb 未 匹配 的 作为 val_no_same_ind_arr
    val_no_same_ind_arr.push(...clone_cur_tb_type_arr);

    let loop_both_arr_to_0 = () => {
      // 剩余项 为 新增 或 删除
      if (val_no_same_ind_arr.length > 0) {
        // 进入 tA 类别 下一次循环
        if (clone_cur_ta_type_arr.length == 0) {
          // 将 当前 剩余 不相同元素 设置为 新增项
          packret_LinkObj(
            linked_arr,
            increase_part_arr(tB, val_no_same_ind_arr),
            'increase_part'
          );
          return;
        }
        // tA 剩余 全 不相同项 但 类型 相同 可能 只是 更改
        if (clone_cur_ta_type_arr.length > 0) {
          let splice_length = Math.min(
            clone_cur_ta_type_arr.length,
            val_no_same_ind_arr.length
          );

          let cur_val_no_same_type_arr = clone_cur_ta_type_arr.splice(
            0,
            splice_length
          );

          val_no_same_ind_arr.splice(0, splice_length);

          let i = 0;

          for (const cur_val_no_same_type_ind of cur_val_no_same_type_arr) {
            ObjectOnlyPushSet(
              linked_arr,
              cur_val_no_same_type_ind,
              value_no_same_part(
                tA[cur_val_no_same_type_ind],
                tB[val_no_same_ind_arr[i++]]
              )
            );
          }
        }
      }

      // 无 全 不相同项
      if (val_no_same_ind_arr.length == 0) {
        // 进入 tA 类别 下一次循环
        if (clone_cur_ta_type_arr.length == 0) {
          return;
        }
        // 当 tA 中 仍有 残留 时
        // 设置为 删除项
        if (clone_cur_ta_type_arr.length > 0) {
          packret_LinkObj(
            linked_arr,
            delete_part_arr(tA, clone_cur_ta_type_arr),
            'delete_part'
          );

          return;
        }
      }
      // 没退出 就继续
      loop_both_arr_to_0();
    };

    loop_both_arr_to_0();

    // /**
    //  * ignore 下面
    //  */

    // let type_val_more_same_emptydata = new emptyData();

    // let type_val_no_same_emptydata = new emptyData();

    // /**
    //  * 复制 数组对象 -- 剩余 项
    //  */
    // let surplus_tA_type_index = empty_clone(<(string | number)[]>tA[key_type]);

    // /**
    //  * 从 tA 为 关键循环 快速 确立 相同 及 相似项
    //  * 以 最先 最高分 为 最优解
    //  */

    // for (const tb_key_type_index of tB[key_type]) {
    //   let for_all_compare = new compare_more_same();

    //   for (const ta_key_type_index of surplus_tA_type_index) {
    //     // 深度 比对 tA[ta_key_type_index], tB[tb_key_type_index] 确立 相似度
    //     ObjectOnlyPushSet(
    //       for_all_compare,
    //       ta_key_type_index,
    //       compare_A_B(tA[ta_key_type_index], tB[tb_key_type_index])
    //     );
    //   }

    //   let { value_same_describe, more_same_index } =
    //     seek_for_more_same(for_all_compare);

    //   switch (value_same_describe) {
    //     // 元素 全相同
    //     case same_describe.allSame:
    //       for_all_compare._$223_same_describe = same_describe.allSame;

    //       surplus_tA_type_index.splice(
    //         surplus_tA_type_index.indexOf(more_same_index),
    //         1
    //       );
    //       // 移除 其他项
    //       remove_other_compeared_result(for_all_compare);

    //       // 添加 最相似项
    //       linked_more_same_ind_arr.push(more_same_index);

    //       // 添加 建立连接 的 信息
    //       ObjectOnlyPushSet(linked_arr, tb_key_type_index, for_all_compare);
    //       break;
    //     case same_describe.moreSame:
    //       for_all_compare._$223_same_describe = same_describe.moreSame;

    //       // 保留 相似 意见
    //       ObjectOnlyPushSet(
    //         type_val_more_same_emptydata,
    //         tb_key_type_index,
    //         for_all_compare
    //       );
    //       continue;
    //     case same_describe.valNoSame:
    //       for_all_compare._$223_same_describe = same_describe.valNoSame;

    //       // 保留 不相似 意见
    //       ObjectOnlyPushSet(
    //         type_val_no_same_emptydata,
    //         tb_key_type_index,
    //         for_all_compare
    //       );
    //       continue;

    //     default:
    //       break;
    //   }
    // }
  }

  return linked_arr;
}

/**
 * 包装 类 类别 新增 或 删除 到 ret
 * @param {compare_linkObj} ret
 * @param {emptyData} obj
 */
function packret_LinkObj(
  ret: compare_linkObj,
  obj: emptyData,
  data: compare_linkObj_data_or_delete_part = 'data'
) {
  let keysArr = obj.data;
  if (ret[data] == undefined) {
    ret[data] = [];
  }
  for (const key of keysArr) {
    let revise_key_ind = `${
      data == 'data' ? '' : data.replace('_part', '') + '_'
    }${key}`;
    ObjectOnlyPushSet(ret, revise_key_ind, obj[key], data);
  }
}

function value_no_same_part(obj_A: any, obj_B: any) {
  return new diff_prop_typeArr.valueNoSame(obj_A, obj_B);
}

function increase_part_arr(
  obj: explore_for_diff,
  keyArr: key_ind_arr | string | number
): emptyData {
  return operate_increase_or_delete_part_arr('increase', obj, keyArr);
}

function delete_part_arr(
  obj: explore_for_diff,
  keyArr: key_ind_arr | string | number
): emptyData {
  return operate_increase_or_delete_part_arr('delete', obj, keyArr);
}

/**
 * 根据 新增 或 删除 系列 对 给定集合 进行 对应 处理
 * @param operate "increase" | "delete" 新增 或 删除
 * @param obj 展开 的 对象
 * @param keyArr 给定集合
 * @returns
 */
function operate_increase_or_delete_part_arr(
  operate: quick_increase_or_delete,
  obj: explore_for_diff,
  keyArr: key_ind_arr | string | number
) {
  let ret = new emptyData();

  if (typeof keyArr == 'string' || typeof keyArr == 'number') {
    keyArr = [keyArr];
  }

  //  ！！！！这里 忽略了 valueNoSame
  for (const key of keyArr) {
    ObjectOnlyPushSet(
      ret,
      key,
      increase_or_delete_part(operate, <explore_for_diff>obj[key])
    );
  }
  return ret;
}

/**
 * 生成 删除 或 新增
 * @param {quick_increase_or_delete} operate 新增 或 删除
 * @param {explore_for_diff} val 展开 的 对象
 * @returns
 */
function increase_or_delete_part<T extends quick_increase_or_delete>(
  operate: T,
  val: explore_for_diff
): quick_increase_or_delete_instance {
  return new diff_prop_typeArr[operate](val);
}

/**
 * 移除 其他 项
 * @param all_compared
 */
function remove_other_compeared_result(all_compared: compare_more_same) {
  for (const key_ind of all_compared.data) {
    if (key_ind != all_compared._$223_more_same_index) {
      delete all_compared[key_ind];
    }
  }
  all_compared.data = [all_compared._$223_more_same_index!];
}

// 2025.07.14 22:31:31 晴 早上 最小的甲鱼 努力 的 在游着 我也意识到 了 可能 游了 一晚上
// 但是 我 没在意 因为 之前 放虾子 没事 我也以为 游一会儿 没事
// 但是 中午 玩玩 到 十点多 的样子 就看见它 翻肚 死了 也可能 是没有换水 身上 有两处伤
// 锁骨 和 左后 裙边 其他无恙 可能 力竭 淹死了 水 的 高度 其实 没有问题 但是 我现在也不敢保证了
// 现在 稍稍 抬头 就能 呼吸到
